#pragma once

#include "Common.hpp"
#include "TcpServer.hpp"
#include "Util.hpp"
#include <string>
#include <cstring>
#include <vector>
#include <unordered_map>
#include <iostream>
#include <sstream>
#include <functional>
#include <poll.h>

const std::string webroot = "./wwwroot"; // web根目录
const std::string homepage = "/index.html"; // 主页
const std::string page_404 = "/404.html"; // 404页

const std::string endline = "\r\n"; // 换行
const std::string space = " "; // 空格
const std::string delim = ": "; // 报头的键值分隔符

//请求报文
class HttpRequest
{
public:
    //反序列化
    void Deserialize(std::string& reqstr)
    {
        //读取请求行
        std::string reqline;
        Util::ReadOneLine(reqstr, &reqline, endline);

        //对请求行进行反序列化 请求方法 + uri + HTTP版本
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version;

        // 读取报头，直到遇到空行
        std::string header_line;
        while (true) {
            Util::ReadOneLine(reqstr, &header_line, endline);
            if (header_line == "\r\n" || header_line == "" || header_line == "\n") {
                break;
            }
            // 可选：这里可以解析header
        }

        // 处理参数
        if (_method == "POST") 
        {
            // POST：正文就是参数
            _args = reqstr; // 剩下的就是正文
            _isexec = true;
        } 
        else 
        {
            // GET：参数在URL
            size_t pos = _uri.find('?');
            if(pos != std::string::npos) 
            {
                _isexec = true; // 标记为动态交互
                _args = _uri.substr(pos + 1); // 提取问号后的参数
                _uri = _uri.substr(0, pos);   // 将URI截断，只保留 /manage_students
            } 
        else 
        {
            // 检查是否是已知的动态路由（硬编码）
            if (_uri == "/manage_students") 
            {
                _isexec = true; // 标记为动态路由
                _args = ""; // 没有参数
            } 
            else 
            {
                // 处理静态文件
                if(_uri == "/") _uri = webroot + homepage; // 如果是根目录，就对应主页
                else _uri = webroot + _uri; // 否则将根目录替换为web根目录名
                _isexec = false;
            }
        }
    }
}

    std::string Uri()
    {
        return _uri;
    }

    bool Isexec()
    {
        return _isexec;
    }

    std::string Args()
    {
        return _args;
    }
private:
    std::string _method; // 请求方法
    std::string _uri; // 访问目标路径
    std::string _version; // HTTP版本
    // std::unordered_map<std::string, std::string> _handers; // 报头
    // std::string blankline = endline; // 空行
    // std::string _text; //报文正文

    std::string _args; // 参数
    bool _isexec = false; // 表示是否有参数（是否需要动态交互）
};

//应答报文
class HttpResponse
{
public:
    //序列化
    std::string Serialize()
    {
        std::string respstr;

        //处理状态行 版本 + 空格 + 状态码 + 空格 + 状态码描述 + 换行
        respstr += _version + space + std::to_string(_code) + space + _desc + endline;

        //处理报头&加入空行
        for(auto& header : _headers)
        {
            respstr += header.first + delim + header.second + endline;
        }
        respstr += endline;

        //处理正文
        respstr += _text;
        return respstr;
    }
    
    //设置目标文件
    void SetTargetFile(const std::string& target)
    {
        _targetfile = target;
    }

    //设置状态码和状态码描述
    void SetCode(int code)
    {
        _code = code;
        switch(code)
        {
            case 200:
                _desc = "OK";
                break;
            case 404:
                _desc = "Not Found";
                break;
            default:
                break;
        }
    }

    //插入一个报头行
    void SetHeader(const std::string key, const std::string value)
    {
        if(_headers.find(key) != _headers.end()) return; // 如果有就不插入
        _headers[key] = value;
    }

    //设置正文
    void SetText(const std::string& text)
    {
        _text = text;
    }

    //构建应答报文
    void MakeResp()
    {
        //读取对应网页
        _text.clear();
        if(!Util::ReadFile(_targetfile, &_text)) // 如果网页不存在，则读取404网页返回
        {
            std::cout << "用户访问网页" << _targetfile << "但不存在" << std::endl;
            SetCode(404);
            _targetfile = webroot + page_404;
            Util::ReadFile(_targetfile, &_text);
        }
        else
        {
            SetCode(200);
        }

        //设置报头Content-Length
        ssize_t filesize = Util::FileSize(_targetfile);
        SetHeader("Content-Length", std::to_string(filesize));
        
        //设置报头Content-type
        std::string type = Util::FileType(_targetfile);
        if(type != "") SetHeader("Content-Type", type);

        //设置报头Connection，表示支持长服务
        SetHeader("Connection", "keep-alive");
    }
private:
    std::string _version = "HTTP/1.1"; // HTTP版本
    int _code; // 状态码
    std::string _desc; // 状态码描述
    std::unordered_map<std::string, std::string> _headers; // 报头
    std::string _blankline = endline; // 空行
    std::string _text;  // 正文

    std::string _targetfile; // 目标页面
};

//定义动态交互接口
typedef std::function<void(HttpRequest&, HttpResponse&)> route_t;

//Http应用层
class Http
{
public:
    Http(uint16_t port) : _tsvr(std::make_shared<TcpServer>(port)) {}

    //启动服务
    void Start()
    {
        _tsvr->Start([this](std::shared_ptr<Socket_t>& sock, InetAddr& client)
        {
            this->AnswerHttpRequest(sock, client);
        });
    }

    //服务端处理报文并作出应答
    void AnswerHttpRequest(std::shared_ptr<Socket_t>& sock, InetAddr& client)
    {
        //超时机制 -- 页面跳转避免内存泄漏
        struct pollfd pfd;
        pfd.fd = sock->GetFd(); // 获取底层文件描述符
        pfd.events = POLLIN; // 监听读事件

        while(true) // 长服务 -- 用户退出才会关闭链接
        {
            //设置超时时间60秒
            int ret = poll(&pfd, 1, 60 * 1000);
            if (ret == -1) 
            {
                // 错误处理
                std::cerr << "poll error" << std::endl;
                break;
            } 
            else if (ret == 0) 
            {
                // 超时，客户端长时间没有发送数据，关闭连接
                break;
            } 
            else 
            {
                //接收客户端的请求报文
                std::string reqstr;
                int n = sock->Recv(&reqstr);
                if(n > 0) // 读到了，进行处理
                {
                    //反序列化
                    HttpRequest req;
                    req.Deserialize(reqstr);

                    HttpResponse resp;
                    //判断是否需要动态交互
                    if(req.Isexec() || _routeMap.count(req.Uri()) > 0)
                    {                     
                        // 检查路由是否存在
                        if (_routeMap.find(req.Uri()) != _routeMap.end())
                        {
                            //执行对应的动态交互方法
                            _routeMap[req.Uri()](req, resp);
                        }
                        else
                        {
                            std::cout << "路由不存在: " << req.Uri() << std::endl;
                            resp.SetCode(404);
                        }
                    }
                    else
                    {
                        //构建应答报文
                        resp.SetTargetFile(req.Uri()); // 设置目标网页
                        resp.MakeResp(); // 根据目标网页构建报文
                    }
                    //序列化
                    std::string respstr = resp.Serialize();

                    //发送应答报文
                    sock->Send(respstr);
                }
                else if(n == 0) // 表示用户退出
                {
                    break;
                }
                else // 读取错误
                {
                    std::cerr << "读取错误" << std::endl;
                    break;
                }
            }
        }
    }

    //动态交互方法注册
    void RegisterService(const std::string& s, route_t func)
    {
        if(_routeMap.find(s) != _routeMap.end()) return;
        _routeMap[s] = func;
    }

private:
    std::shared_ptr<TcpServer> _tsvr; // TCP服务端
    std::unordered_map<std::string, route_t> _routeMap; //动态交互的映射表
};